package org.yray.sip.rtp.server;


import io.netty.buffer.ByteBuf;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.DatagramPacket;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.yray.sip.packet.BasePacket;
import org.yray.sip.receive.BasePacketDispatch;
import org.yray.sip.rtp.sender.RtcpPacket;
import org.yray.sip.server.SipServerContext;

import java.net.InetSocketAddress;
import java.util.Arrays;

@Slf4j
public class UrtcpServerHandler extends SimpleChannelInboundHandler<DatagramPacket> {

    private Channel channel;

    public SipServerContext getSipServerContext() {
        return sipServerContext;
    }


    @Autowired
    private BasePacketDispatch basePacketDispatch;

    private SipServerContext sipServerContext;

    public UrtcpServerHandler(SipServerContext sipServerContext)
    {
        this.sipServerContext = sipServerContext;
        sipServerContext.setUrtcpServerHandler(this);
    }

    public Channel getChannel() {
        return channel;
    }

    public void setChannel(Channel channel) {
        this.channel = channel;
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        //关闭之后会导致netty不可用，udp是单通道的 尽量防止异常抛到这里
        ctx.close();
        log.error(cause.getMessage(), cause);
    }

    //发送udp数据包 注意gbk编码
    public void send(byte[] msg, InetSocketAddress sender) {
        ByteBuf byteBuf = Unpooled.copiedBuffer(msg);
        channel.writeAndFlush(new DatagramPacket(byteBuf, sender));
        log.debug("send to {},{}", sender.getAddress().getHostAddress(), sender.getPort());
        log.debug("--------------------------------------------------------------");
        log.debug("msg={}", Arrays.toString(msg));
    }

    public void sendUdp(byte[] msg, InetSocketAddress sender) {
        ByteBuf byteBuf = PooledByteBufAllocator.DEFAULT.directBuffer(1024);
        byteBuf.writeBytes(msg);
        channel.writeAndFlush(new DatagramPacket(byteBuf, sender));
        byteBuf.release();
        log.debug("send to {},{}", sender.getAddress().getHostAddress(), sender.getPort());
        log.debug("--------------------------------------------------------------");
        log.debug("msg={}", Arrays.toString(msg));
    }


    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, DatagramPacket packet) throws Exception {
    {
        //去除空包，公网状态下很多空包 应该是服务器端口被探测
        InetSocketAddress sender = packet.sender();
        log.debug("{},receive from [{},{}]", System.currentTimeMillis(), sender.getAddress().getHostAddress(), sender.getPort());
        log.debug(" -----------------------------------------------------");
        if (packet.content().readableBytes() < 1)
            return;
        byte[] data = new byte[packet.content().readableBytes()];
        packet.content().readBytes(data);
        try {
            if(BasePacket.instanceOf(data))
            {
                basePacketDispatch.dispatch(data);
            }
            else {
                RtcpPacket.formatRtcp(data);
            }


        } catch (Exception e) {
            log.error("Exception:{}", ExceptionUtils.getStackTrace(e));
        }

    }

    }
}

